package com.xyzwps.server.paimon.model.repository

import com.xyzwps.server.paimon.model.entity.PhoneVcode
import com.xyzwps.server.paimon.model.table.PhoneVcodeTable
import com.xyzwps.server.paimon.value.Phone
import com.xyzwps.server.paimon.value.VcodeScene
import com.xyzwps.server.paimon.value.toVcodeScene
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.greater
import org.jetbrains.exposed.v1.jdbc.insertAndGetId
import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.update
import org.springframework.stereotype.Repository
import kotlin.time.Instant


internal val v = PhoneVcodeTable

fun rowToPhoneVcode(it: ResultRow): PhoneVcode {
    return PhoneVcode(
        id = it[v.id].value,
        phone = Phone(it[v.phone]),
        scene = it[v.scene].toVcodeScene(),
        vcode = it[v.vcode],
        dkey = it[v.dkey],
        createdAt = it[v.createdAt],
        used = it[v.used],
        usedAt = it[v.usedAt]
    )
}

@Repository
class PhoneVcodeRepository() {

    fun findByPhoneAndSceneAndCreatedAtAfter(phone: Phone, scene: VcodeScene, createdAt: Instant): List<PhoneVcode> =
        PhoneVcodeTable.selectAll()
            .where { (v.phone eq phone.value) and (v.scene eq scene.value) and (v.createdAt greater createdAt) }
            .map { rowToPhoneVcode(it) }
            .toList()

    fun save(phoneVcode: PhoneVcode): PhoneVcode {
        if (phoneVcode.id == null) {
            val id = PhoneVcodeTable.insertAndGetId {
                it[phone] = phoneVcode.phone.value
                it[scene] = phoneVcode.scene.value
                it[vcode] = phoneVcode.vcode
                it[dkey] = phoneVcode.dkey
                it[createdAt] = phoneVcode.createdAt
                it[used] = phoneVcode.used
                it[usedAt] = phoneVcode.usedAt
            }
            return phoneVcode.copy(id = id.value)
        }

        PhoneVcodeTable.update({ v.id eq phoneVcode.id }) {
            it[phone] = phoneVcode.phone.value
            it[scene] = phoneVcode.scene.value
            it[vcode] = phoneVcode.vcode
            it[dkey] = phoneVcode.dkey
            it[createdAt] = phoneVcode.createdAt
            it[used] = phoneVcode.used
            it[usedAt] = phoneVcode.usedAt
        }
        return phoneVcode
    }
}
